/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.huawei.spare.part.replace.views.replace.uplink;

import com.huawei.spare.part.replace.framework.SmartContentPresenter;
import com.huawei.spare.part.replace.framework.SmartDataBus;
import com.huawei.spare.part.replace.models.Replacement;
import com.huawei.spare.part.replace.models.Switch;
import com.huawei.spare.part.replace.models.Uplink;
import com.huawei.spare.part.replace.views.widgets.Alerts;
import com.huawei.spare.part.replace.views.widgets.cell.EditCell;
import io.reactivex.Observable;
import io.reactivex.rxjavafx.observables.JavaFxObservable;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javafx.application.Platform;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Woo
 */
public class UplinkPresenter extends SmartContentPresenter {

  private static final Logger log = LoggerFactory.getLogger(UplinkPresenter.class);

  @FXML TableView uplinkTable;
  @FXML TableColumn<Uplink, String> switchPortColumn;
  @FXML TableColumn<Uplink, String> businessPortColumn;
  @FXML TableColumn<Uplink, String> remarkColumn;
  @FXML TableColumn<Uplink, Void> operationColumn;
  @FXML Button addRecordButton;

  ObservableList<String> switchPorts;
  ObservableList<Uplink> uplinks = FXCollections.observableArrayList();

  @Override
  public void initialize() {
    JavaFxObservable.changesOf(uplinks).subscribe((e) -> {
      addRecordButton.disableProperty().set(uplinks.size() == switchPorts.size());
    });

    Platform.runLater(() -> {
      final Switch switch0 = SmartDataBus.get().replacement().getProject().getSwitch0();
      final Replacement.Slot slot = SmartDataBus.get().replacement().getSlot();
      this.switchPorts = FXCollections.observableArrayList(switch0.getPorts(slot.getPos()));
      initialTableView();
    });
  }

  /**
   * 初始化表格渲染
   */
  private void initialTableView() {
    // Cell selectable
    uplinkTable.getSelectionModel().cellSelectionEnabledProperty().set(true);

    switchPortColumn.setCellValueFactory(new PropertyValueFactory("switchPort"));
    businessPortColumn.setCellValueFactory(new PropertyValueFactory("businessPort"));
    remarkColumn.setCellValueFactory(new PropertyValueFactory("remark"));

    switchPortColumn.setCellFactory(ComboBoxTableCell.forTableColumn(this.switchPorts));
    businessPortColumn.setCellFactory(column -> EditCell.createStringEditCell());
    remarkColumn.setCellFactory(column -> EditCell.createStringEditCell());
    operationColumn.setCellFactory(param -> new TableCell<Uplink, Void>() {
      private final Button delete = new Button(getString("button.delete"));
      private final HBox actionBox = new HBox();

      {
        actionBox.getStyleClass().add("uplink-action-box");
        actionBox.getChildren().add(delete);
        JavaFxObservable.eventsOf(delete, MouseEvent.MOUSE_CLICKED)
            .throttleFirst(500, TimeUnit.MILLISECONDS)
            .subscribe((e) -> {
              Uplink uplink = getTableView().getItems().get(getIndex());
              uplinks.remove(uplink);
            });
      }

      @Override
      protected void updateItem(Void item, boolean empty) {
        super.updateItem(item, empty);
        setGraphic(empty ? null : actionBox);
      }
    });

    switchPortColumn.setOnEditCommit(event -> {
      final Uplink uplink = event.getTableView().getItems().get(
          event.getTablePosition().getRow());
      final String port = event.getNewValue();
      if (!getCommittedPorts().contains(port)) {
        uplink.switchPortProperty().set(port);
      } else {

      }
    });

    businessPortColumn.setOnEditCommit(event -> {
      final Uplink uplink = event.getTableView().getItems().get(
          event.getTablePosition().getRow());
      uplink.businessPortProperty().set(event.getNewValue());
    });

    remarkColumn.setOnEditCommit(event -> {
      final Uplink uplink = event.getTableView().getItems().get(
          event.getTablePosition().getRow());
      uplink.remarkProperty().set(event.getNewValue());
    });

    uplinkTable.setItems(uplinks);
  }

  private List<String> getCommittedPorts() {
    return uplinks.stream()
        .map(Uplink::switchPortProperty)
        .map(StringProperty::get)
        .collect(Collectors.toList());
  }

  @FXML
  private void onAddUplink() {
    final List<String> committedPorts = getCommittedPorts();
    final Optional<String> first = this.switchPorts.stream().filter((p) -> !committedPorts.contains(p)).findFirst();
    if (first.isPresent()) {
      uplinks.add(new Uplink(first.get(), "", ""));
    }
  }

  @Override
  public Observable<Boolean> onFinish() {
    SmartDataBus.get().replacement().setUplinks(uplinks);
    if (uplinks.size() == 0) {
      final Optional<ButtonType> confirm = Alerts.confirm("common.title.op.confirm", "uplink.no.record.confirm");
      return Observable.just(confirm.get().equals(ButtonType.OK));
    }

    //snapshotUplinkTable();
    return Observable.just(true);
  }

  private void snapshotUplinkTable() {
    uplinkTable.getSelectionModel().clearSelection();
    WritableImage snapshot = uplinkTable.snapshot(new SnapshotParameters(), null);
    SmartDataBus.get().replacement().setUplinkTableSnapshot(snapshot);
    container.getChildren().add(new ImageView(snapshot));
  }
}
